﻿using System;
using System.Collections.Generic;
using System.Linq;
using QueryResource.Common;
using DBAccessLibrary.Common;
using DBAccessLibrary.Model;
using DBAccessLibrary;
using System.Collections.ObjectModel;
using System.Windows;
using System.Threading.Tasks;
using System.Windows.Media;
namespace QueryResource.ViewModel
{
    public class DBTreeViewModel : BasePropertyChange
    {
        private const string FileName = "data.dat";
        private const string Backfilename = "backupdata.dat";
        private DataBaseEntity _selectedItem;

        public DBTreeViewModel()
        {
            //连接数据库
            ConnectDBCommand = new DelegateCommand<DBEntity>(ChangeDBConnectionStatus, entity =>
            {
                if (this.SelectedItem == null)
                    return false;
                DBEntity db = this.SelectedItem as DBEntity;
                if (db == null || db.ConnectionSource == null)
                    return false;
                return db.Status == DBConnectStatus.Off;
            });
            //断开数据库
            UnConnectDBCommand = new DelegateCommand<DBEntity>(entity =>
            {
                entity.Status = DBConnectStatus.Off;
                WriteDBInfo("", "", "");
                this.SelectedItem = entity;
            }, entity =>
            {
                if (this.SelectedItem == null)
                    return false;
                DBEntity db = this.SelectedItem as DBEntity;
                if (db == null)
                    return false;
                return db.Status == DBConnectStatus.Connected;
            });
            //修改当前连接
            EditConnectDBCommand = new DelegateCommand<DBEntity>(entity=>{
                if (ShowRegister != null)
                {
                    ShowRegister(entity);
                }
            }, entity =>
            {
                if (this.SelectedItem == null)
                    return false;
                DBEntity db = this.SelectedItem as DBEntity;
                if (db == null)
                    return false;
                return true;
            });
            //查询SQL
            SelectAllCommand = new DelegateCommand<TableEntity>(entity => WriteSql(entity.SelectAll(), SqlControlStatus.NoRun | SqlControlStatus.NewLine));
            //查询前100
            SelectTopCommand = new DelegateCommand<TableEntity>(entity => WriteSql(entity.SelectTop(), SqlControlStatus.NoRun | SqlControlStatus.NewLine));
            //查询并执行
            SelectRunCommand = new DelegateCommand<TableEntity>(entity => WriteSql(entity.SelectAll(), SqlControlStatus.Run | SqlControlStatus.NewLine));
            //复制
            CopyCommand = new DelegateCommand<DataBaseEntity>(entity =>
            {
                try
                {
                    Clipboard.SetText(entity.TransName);
                }
                catch { }
            });
            //显示新窗体
            ShowNewWindowCommand = new DelegateCommand<ViewEntity>(entity => WriteWindow(entity.Name, entity.Content));
            //删除数据库
            DeleteCommand = new DelegateCommand<DataBaseEntity>(entity =>
            {
                DataBaseEntity root = this.DataSource.FirstOrDefault(o => o.ChildNodes.FirstOrDefault(p => p.Equals(entity)) != null);
                if (root != null)
                {
                    root.ChildNodes.Remove(entity);
                }
                else
                {
                    root =this.DataSource.FirstOrDefault(o => o.Equals(entity));
                    if (root != null)
                        this.DataSource.Remove(root);
                }
                WriteData();
            }, entity =>
            {
                if (this.SelectedItem == null)
                    return false;
                return this.SelectedItem != null;
            });
            //中英转换
            TransFormCommand = new DelegateCommand<DataBaseEntity>(entity => entity.ChildNodes[0].TransForm());
            //导出表结构
            ExprotTableStructureCommand = new DelegateCommand<TableEntity>(entity =>
            {
                string createsql = DBOperatorFactory.GetGrammar(SysCache.DBConnection).GetCreateInfo(SysCache.DBConnection.ConnectType,entity);
                //新加一个窗口 
                WriteSqlContent(entity.Name, createsql);
                //WriteSQL(sql, false, true);
            }, entity =>
            {
                if (this.SelectedItem == null)
                    return false;
                return (this.SelectedItem as TableEntity) != null;
            });
            //刷新
            RefreshCommand = new DelegateCommand<DBEntity>(entity =>
                                                               {
                                                                   try
                                                                   {
                                                                       Connection();
                                                                   }
                                                                   catch (Exception ex)
                                                                   {
                                                                       WriteLog(ex.Message,Colors.Red);
                                                                   }
                                                               }
                );
            //添加描述
            AddDescriptionCommand = new DelegateCommand<TableEntity>(entity =>
            {
                if (ShowDescriptionWindows != null)
                    ShowDescriptionWindows(entity);
            });
            //显示存储过程执行命令
            ShowProcInfoCommand = new DelegateCommand<ProcEntity>(entity =>
            {
                if (entity == null)
                    return;
                WriteSql(
                    DBOperatorFactory.GetGrammar(SysCache.DBConnection).GetProcParamInfo(entity)
                    , SqlControlStatus.NoRun | SqlControlStatus.NewLine);
            });
            //添加列
            AddColumnInfoCommand = new DelegateCommand<FieldEntity>(entity =>
                                                                        {
                                                                            if (entity == null)
                                                                                return;
                                                                            WriteSql(entity.AddColumnSql, SqlControlStatus.NoRun | SqlControlStatus.NewLine);
                                                                        });
            //表定义
            TableDefinitionCommand = new DelegateCommand<TableEntity>(entity =>
                                                                          {
                                                                              if (entity == null)
                                                                                  return;
                                                                              if (ShowTableDefinition != null)
                                                                                  ShowTableDefinition(entity);
                                                                          });
        }

        /// <summary>
        /// 连接数据库
        /// </summary>
        public bool Connection()
        {
            if (SysCache.DBConnection == null)
            {
                AppendLogAction("当前连接不可用", Colors.Red);
                return false;
            }
            Action action = () =>
            {

                if (DBOperatorFactory.GetOperator.CreateDBEntity(SysCache.ServerList,
                                                                 (o, c) =>
                                                                 AppendLogAction(o, c),
                                                                 TreeViewBegionInvoke))
                {
                    WriteDBInfo(SysCache.DBConnection.Server, SysCache.DBConnection.DataBase,
                                SysCache.DBConnection.UserID);
                }
            };
            Task.Factory.StartNew(action).ContinueWith(t => {
                if (t.Exception != null)
                {
                    WriteLog(t.Exception.Message, Colors.Red);
                }
                else
                {
                    WriteData();
                }
            });
            return true;
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        public void LoadData()
        {
            var data = DataCompression.DeserializeDataToFile<List<DataBaseEntity>>(FileName,false);
            if (data != null)
            {
                SysCache.ServerList = new ObservableCollection<DataBaseEntity>(data.Where(o=>o!= null));
            }
            else
            {
                //查看备份文件 是否保存有数据
                data = DataCompression.DeserializeDataToFile<List<DataBaseEntity>>(Backfilename, false);
                SysCache.ServerList = data != null ? 
                    new ObservableCollection<DataBaseEntity>(data) 
                    : 
                    new ObservableCollection<DataBaseEntity>();
            }

            foreach (DataBaseEntity entity in SysCache.ServerList)
            {
                foreach (DataBaseEntity dbEntity in entity.ChildNodes)
                {
                    DBEntity db = dbEntity as DBEntity;
                    if (db != null && db.Status == DBConnectStatus.Connected)
                    {
                        db.Status = DBConnectStatus.Off;
                        ChangeDBConnectionStatus(db);
                        break;
                    }
                }
            }
        }

        public void WriteData()
        {
            if (SysCache.ServerList != null)
            {
                List<DataBaseEntity> dbList = SysCache.ServerList.Select(entity => entity.Copy()).ToList();

                //由于可能在 序列化保存的时候 关系系统造成 数据丢失 顾多保存一次备份数据
                dbList.SerializeDataToFile(AppDomain.CurrentDomain.BaseDirectory + "\\" + Backfilename, false);
                dbList.SerializeDataToFile(AppDomain.CurrentDomain.BaseDirectory + "\\" + FileName, false);
                WriteLog("记录连接状态成功", Colors.Black);
            }
        }
        /// <summary>
        /// 将当前实体 改成连接状态 其他相同节点改成断开状态
        /// </summary>
        /// <param name="dbEntity"></param>
        private void ChangeDBConnectionStatus(DBEntity dbEntity)
        {
            if (dbEntity == null)
                return;
            //改变状态
            foreach (DataBaseEntity serverEntity in SysCache.ServerList)
            {
                foreach (DataBaseEntity entity in serverEntity.ChildNodes.Where(o => o.Name != dbEntity.Name))
                {
                    ((DBEntity) entity).Status = DBConnectStatus.Off;
                }
            }
          
            dbEntity.Status = DBConnectStatus.Connected;
            if (dbEntity.ChildNodes.Count == 0)
            {
                if (!Connection())
                    dbEntity.Status = DBConnectStatus.Off;
            }
            else
            {
                dbEntity.IsExpanded = true;
                WriteDBInfo(SysCache.DBConnection.Server, SysCache.DBConnection.DataBase, SysCache.DBConnection.UserID);
                this.SelectedItem = dbEntity;
            }
        }

        /// <summary>
        /// 数据源
        /// </summary>
        public ObservableCollection<DataBaseEntity> DataSource
        {
            get { return SysCache.ServerList; }
            set
            {
                if (SysCache.ServerList != value)
                {
                    SysCache.ServerList = value;
                    this.NotifyPropertyChanged(o => o.DataSource);
                }
            }
        }

        /// <summary>
        /// 当前选择
        /// </summary>
        public DataBaseEntity SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                if (value != null)
                {
                    if (_selectedItem != value)
                    {
                        _selectedItem = value;
                        WriteFieldCaption(_selectedItem.TransChName);
                        this.NotifyPropertyChanged(o => o.SelectedItem);
                    }
                }
            }
        }

        #region 命令集
        //连接数据库命令
        public DelegateCommand<DBEntity> ConnectDBCommand { get; set; }
        //断开数据库命令
        public DelegateCommand<DBEntity> UnConnectDBCommand { get; set; }
        //修改数据库连接
        public DelegateCommand<DBEntity> EditConnectDBCommand { get; set; }
        //查询语句命令
        public DelegateCommand<TableEntity> SelectAllCommand { get; set; }
        //查询前100
        public DelegateCommand<TableEntity> SelectTopCommand { get; set; }
        //查询并执行命令
        public DelegateCommand<TableEntity> SelectRunCommand { get; set; }
        //复制命令
        public DelegateCommand<DataBaseEntity> CopyCommand { get; set; }
        //显示新窗体
        public DelegateCommand<ViewEntity> ShowNewWindowCommand { get; set; }
        //删除数据库
        public DelegateCommand<DataBaseEntity> DeleteCommand { get; set; }
        //中英文转换
        public DelegateCommand<DataBaseEntity> TransFormCommand { get; set; }
        //导出表结构
        public DelegateCommand<TableEntity> ExprotTableStructureCommand { get; set; }
        //刷新
        public DelegateCommand<DBEntity> RefreshCommand { get; set; }
        //添加描述
        public DelegateCommand<TableEntity> AddDescriptionCommand { get; set; }
        //执行存储过程命令
        public DelegateCommand<ProcEntity> ShowProcInfoCommand { get; set; }
        //添加列
        public DelegateCommand<FieldEntity> AddColumnInfoCommand { get; set; }
        //表定义
        public DelegateCommand<TableEntity> TableDefinitionCommand { get; set; }

        #endregion

        #region 外界通信

        public Action<string, SqlControlStatus> AppendSqlAction
        {
            private get;
            set;
        }
        public Action<string, Color> AppendLogAction
        {
            private get;
            set;
        }
        public Action<string, string> AppendWindow
        {
            private get;
            set;
        }
        public Action<string, string, string> AppendDBInfo
        {
            private get;
            set;
        }
        public Action<string> AppendFieldCaption
        {
            private get;
            set;
        }
        public Action<string, string,bool> AppendSqlContent { private get; set; }

        public Action<TableEntity> ShowDescriptionWindows { get; set; }
        public Action<TableEntity> ShowTableDefinition { get; set; }
        public Action<Action> TreeViewBegionInvoke { get; set; }
        public Action<DBEntity> ShowRegister { get; set; }

        private void WriteSql(string sql, SqlControlStatus status)
        {
            if (AppendSqlAction != null)
            {
                AppendSqlAction(sql, status);
            }
        }
        private void WriteLog(string log, Color isError)
        {
            if (AppendLogAction != null)
            {
                AppendLogAction(log, isError);
            }
        }
        private void WriteWindow(string caption, string content)
        {
            if (AppendWindow != null)
                AppendWindow(caption, content);
        }
        private void WriteDBInfo(string ip, string dbname, string userid)
        {
            if (AppendDBInfo != null)
                AppendDBInfo(ip, dbname, userid);
        }
        private void WriteFieldCaption(string caption)
        {
            if (AppendFieldCaption != null)
                AppendFieldCaption(caption);
        }
        private void WriteSqlContent(string tableName, string content)
        {
            if (AppendSqlContent != null)
            {
                AppendSqlContent(tableName, content, false);
            }
        }
        #endregion
    }
}
